#ifndef __WD_FUNC_H
#define __WD_FUNC_H

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <error.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/epoll.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <sys/uio.h>
#include <sys/sendfile.h>
#include <sys/sendfile.h>

#define SIZE(a) (sizeof(a)/sizeof(a[0]))

typedef void (*sighandler_t)(int);

#define ARGS_CHECK(argc, num)   {\
    if(argc != num){\
        fprintf(stderr, "ARGS ERROR!\n");\
        return -1;\
    }}

#define ERROR_CHECK(ret, num, msg) {\
    if(ret == num) {\
        perror(msg);\
        return -1;\
    }}

#define THREAD_ERROR_CHECK(ret, func) {\
    if(ret != 0) {\
        fprintf(stderr, "%s:%s\n", func, strerror(ret));\
    }}

typedef enum {
    CMD_TYPE_PWD=1,
    CMD_TYPE_LS,
    CMD_TYPE_CD,
    CMD_TYPE_MKDIR,
    CMD_TYPE_RMDIR,
    CMD_TYPE_PUTS,
    CMD_TYPE_GETS,
    CMD_TYPE_TREE,
    CMD_TYPE_QUIT,
    CMD_TYPE_NOTCMD,  //不是命令
    
    CMD_TYPE_REGISTER1=100, 
    CMD_TYPE_REGISTER1_ERROR,                                       
    CMD_TYPE_REGISTER1_RIGHT,
    CMD_TYPE_REGISTER2,
    CMD_TYPE_REGISTER2_ERROR,
    CMD_TYPE_REGISTER2_RIGHT,

    CMD_TYPE_LOGIN1=200, 
    CMD_TYPE_LOGIN1_ERROR,                                       
    CMD_TYPE_LOGIN1_RIGHT,
    CMD_TYPE_LOGIN2,
    CMD_TYPE_LOGIN2_ERROR,
    CMD_TYPE_LOGIN2_RIGHT,
    CMD_TYPE_LOGIN_PIPE,

    //秒传
    CMD_TYPE_SECOND_TRANSMIT = 300,
    CMD_TYPE_NORMAL_TRANSMIT,
    CMD_TYPE_FILE_NOT_EXIST,
    CMD_TYPE_FILE_EXIST
}CmdType;

typedef struct 
{
    int len;//记录内容长度
    CmdType type;
    char buff[1000];//记录内容本身
}train_t;

typedef struct task_s{
    int peerfd;
    CmdType type;
    int epfd;
    char data[1000];
    struct task_s * pNext;
}task_t;

typedef struct task_queue_s
{
    task_t * pFront;
    task_t * pRear;
    int queSize;//记录当前任务的数量
    pthread_mutex_t mutex; 
    pthread_cond_t cond;
    int flag;//0 表示要退出，1 表示不退出

}task_queue_t;
//表示连接到的新端口                                                                                                      
typedef struct arg_t{
    char ip[50];
    char port[10];
}thread_arg_t;

typedef struct t_task_t{
    int peerfd;
    train_t train;
}thread_task_t;

typedef struct threadpool_s {
    pthread_t * pthreads;
    int pthreadNum;
    task_queue_t que;//...任务队列
}threadpool_t;

int queueInit(task_queue_t * que);
int queueDestroy(task_queue_t * que);
int queueIsEmpty(task_queue_t * que);
int taskSize(task_queue_t * que);
int taskEnque(task_queue_t * que, task_t * task);
task_t * taskDeque(task_queue_t * que);
int broadcastALL(task_queue_t* que);

int threadpoolInit(threadpool_t *, int num);
int threadpoolDestroy(threadpool_t *);
int threadpoolStart(threadpool_t *);
int threadpoolStop(threadpool_t *);


int tcpInit(const char * ip, const char * port);
int addEpollReadfd(int epfd, int fd);
int delEpollReadfd(int epfd, int fd);
int transferFile(task_t*task);
int sendn(int sockfd, const void * buff, int len);
int recvn(int sockfd, void * buff, int len);

//验证客户端的注册消息
void register1Command(task_t * task);
void register2Command(task_t * task);

//server端线程的函数
void thread_HandleMessage(task_t * task);
void thread_do_task(task_t * task);

//验证客户端的登录信息
void userlogin1Command(task_t * task);
void userlogin2Command(task_t * task);

//处理客户端发过来的消息
void handleMessage(int sockfd, int epfd, task_queue_t * que);
void serverconf(const char * filename,char *ip ,char *port ,int *threadNum);
//执行任务的总的函数
void doTask(task_t * task);
//每一个具体命令的执行
void cdCommand(task_t * task);
void lsCommand(task_t * task);
void pwdCommand(task_t * task);
void mkdirCommand(task_t * task);
void rmdirCommand(task_t * task);
void notCommand(task_t * task);
void putsCommand(task_t * task);
void getsCommand(task_t * task);
void treeCommand(task_t * task);
void quitCommand(task_t * task);

//断点续传

// 文件日志
void logMessage(const char *message);
void logCLientConnection(int client_fd);
void logClientRequest(int client_fd, const char *request);
#endif
